<?php
	
	class ActiveCollection implements ArrayAccess, Countable, Iterator {
		
    private $_array = array();
    
    
    
    public function to_array() {
      return $this->_array;
    }
    
    public function __construct($array = null) {
      if ($array == null) 
        $array = array();
      $this->_array = $array;
      return $this;
    }
    
    private function _set_first($key) {
      if (isset($this->_first))
        if (is_subclass_of(get_class($this->_array[$this->_first]), 'ActiveRecord'))
          $this->_array[$this->_first]->set_first(false);
      $this->_first = $key;
      if (is_subclass_of(get_class($this->_array[$this->_first]), 'ActiveRecord'))
        $this->_array[$this->_first]->set_first(true);
    }
    
    private function _set_last($key) {
      if (isset($this->_last))
        if (is_subclass_of(get_class($this->_array[$this->_last]), 'ActiveRecord'))
          $this->_array[$this->_last]->set_last(false);
      $this->_last = $key;
      if (is_subclass_of(get_class($this->_array[$this->_last]), 'ActiveRecord'))
        $this->_array[$this->_last]->set_last(true);
    }

    public function offsetExists($offset) {
        return array_key_exists($offset, $this->_array);
    }

    public function offsetGet($offset) {
        return $this->_array[$offset];
    }

    public function offsetSet($offset, $value) {
        $this->_array[$offset] = $value;
    }

    public function offsetUnset($offset) {
        unset($this->_array[$offset]);
    }
    
    public function count() {
      return count($this->_array);
    }
    
    public function current() {
      return current($this->_array);
    }
    
    public function key() {
      return key($this->_array);
    }
    
    public function next() {
      return next($this->_array);
    }
    
    public function rewind() {
      return reset($this->_array);
    }
    
    public function valid() {
      return current($this->_array);
    }
    
    public function __toString() {
      return strval($this->_array);
    }
    
    
    
    # OOPed basic functions
    public function reverse($preserve_keys = false) {
      $this->_array = false;
      pc($this);
      return $this;
    }
    
    public function push() {
      $args = func_get_args();
      $args = str_replace('\'', '\\\'', $args);
      eval ('array_push($this->_array, \'' . join ('\', \'', $args) . '\');');
      return $this;
    }
    
    public function unshift() {
      $args = func_get_args();
      $args = str_replace('\'', '\\\'', $args);
      eval ('array_unshift($this->_array, \'' . join ('\', \'', $args) . '\');');
      return $this;
    }
    
    public function pop($elements = 1) {
      $obj = clone $this;
      for ($i = 1; $i <= $elements; $i++) {
        array_pop($obj->_array);
      }
      if ($elements == 0) {
        $obj->_array = array();
      }
      return $obj;
    }
    
    public function shift($elements = 1) {
      $obj = clone $this;
      for ($i = 1; $i <= $elements; $i++) {
        array_shift($obj->_array);
      }
      if ($elements == 0) {
        $obj->_array = array();
      }
      return $obj;
    }
    
    public function join($separator) {
      return join($separator, $this->_array);
    }
    
    public function unique() {
      $obj = clone $this;
      $obj->_array = array_unique($obj->_array);
      return $obj;
    }
    
    public function sort() {
      $obj = clone $this;
      sort($obj->_array);
      $obj->_set_first(0);
      $obj->_set_last(count($obj->_array) - 1);
      return $obj;
    }
    
    public function includes($element) {
      if (in_array($element, $this->_array)) {
        return true;
      } else {
        return false;
      }
    }
    
    public function map ($function) {
      $obj = clone $this;
      $obj->_array = array_map($function, $obj->_array);
      return $obj;
    }        public function implode ($separator, $prefix = '') {      $str = implode ($separator . $prefix, $this->_array);      if ($str == '') {        return $str;      } else {        return $prefix . $str;      }    }
    
    public function add_keys ($keys_array) {
      if (is_a($keys_array, 'Collection')) {
        $keys_array = $keys_array->to_array();
      }
      $obj = clone $this;                  if (count($keys_array) == count ($obj->_array)) {        if (count($keys_array) == 0) {          $obj->_array = array();        } else {
          $obj->_array = array_combine($keys_array, $obj->_array);        }      } else {        die('Keys and values arrays haven\'t got the same amount of elements.');      }
      return $obj;
    }        public function tree ($parent_name = false) {      if (!$parent_name) {        Logger()->err("You must specify argument for tree: it should be `parent_id type field` in the same table.");      }      $obj = clone $this;      $new_items = array();      foreach ($obj as $id => $item) {        if ($obj[$item->$parent_name]) {          $obj[$item->$parent_name]->children[] = $item;        } else {          $new_items[] = $item;        }      }            return $new_items;    }                public function first() {            $arr = array_values($this->_array);      return $arr[0];    }        public function last() {      $arr = array_values($this->_array);      return $arr[count($arr) - 1];    }        function random () {      $arr = array_values($this->_array);      return $arr[rand (0, count($arr)-1)];    }
    
    
    
    
    
    public function keys() {
      $obj = $this->to_array();
      $obj = array_keys($obj);
      $obj = new ActiveCollection ($obj);
      return $obj;
    }
    
}











  ## active constructor
  function ActiveCollection() {
    return new ActiveCollection (func_get_args());
  }


	
?>